package com.fanrui.code.chess.mahjong.round;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import com.fanrui.code.chess.mahjong.AbstractMahjongTable;
import com.fanrui.code.chess.mahjong.Mahjong;
import com.fanrui.code.chess.mahjong.MahjongGamer;
import com.fanrui.code.chess.mahjong.MahjongIncome;
import com.fanrui.code.chess.mahjong.MahjongIncome.MahjongIncomeInfo;
import com.fanrui.code.chess.mahjong.MahjongStandings.StandingsOperationType;
import com.fanrui.code.chess.mahjong.StandingsRound;
import com.fanrui.code.mahjong.util.MahjongCardUtil;
import com.fanrui.proto.cmd.EveryHuType.IconmeType;
import com.fanrui.proto.cmd.MahjongGroup;
import com.fanrui.proto.cmd.MahjongGroup.GroupType;
import com.fanrui.proto.cmd.NotifyPlayerOperation;
import com.fanrui.proto.cmd.Operation;
import com.fanrui.proto.cmd.ResPlayerOperation.Result;
import com.google.gson.annotations.Expose;


/**
 * @ClassName: MahjongGangRound
 * @Description: 杠回合
 * @author bear
 */
public class MahjongGangRound extends MahjongRound {
	private final static List<Operation> CANRESPONSE = Arrays.asList(Operation.ZIMO, Operation.SEND, Operation.GANG_A,
			Operation.GANG_B);
	@Expose
	protected MahjongOperationResponse response;
	private int deleteNum;
	private MahjongOperationResponse scoure;
	private Collection<Mahjong> operationCard;

	public MahjongGangRound(MahjongOperationResponse scoure, long currentId, AbstractMahjongTable<?> table,
			MahjongOperationResponse response, int deleteNum) {
		super(currentId, CANRESPONSE, table);
		this.response = response;
		this.deleteNum = deleteNum;
		this.scoure = scoure;
	}

	@Override
	public Result addResponse(MahjongOperationResponse response) {
		Result result = canOperationType(response);
		if (result != Result.Success) {
			return result;
		}

		// TODO 多处使用以下代码 请修正
		MahjongGamer gamer = table.getGamerByPlayerID(response.getOperationId());
		Mahjong operationCard = response.getCard();
		if (gamer == null || operationCard == null) {
			return Result.ParameterInvalid;
		}
		if (response.getType() == Operation.GANG_B || response.getType() == Operation.GANG_A) {// 杠碰牌
																								// 查看玩家是否能碰
			int needNum = response.getType() == Operation.GANG_B ? 1 : 4;

			if (MahjongCardUtil.getInstance().getCardNumFromHand(operationCard, gamer.getHandCards()) < needNum) {
				return Result.NotHavaCard;
			}

			if (response.getType() == Operation.GANG_B) {
				boolean haveGroup = false;
				for (MahjongGroup group : gamer.getGroup()) {
					if (group.getType() == GroupType.PENG
							&& MahjongCardUtil.getInstance().toMahjongCard(group.getMjs(0)).cardEquals(operationCard)) {
						haveGroup = true;
						break;
					}
				}
				if (!haveGroup) {
					return Result.BaGangInvalid;
				}
			}
		}

		if (response.getType() == Operation.ZIMO) {
			if (!MahjongCardUtil.getInstance().checkHu(operationCard, gamer, table.getGameRules())) {
				return Result.CantHu;
			}
		}
		// 判断是否能够加入到操作中
		addResponseToList(response);
		return result;
	}

	@Override
	public synchronized Object doResponse() {
		if(isDoResponse){
			return null;
		}
		isDoResponse = true;
		if (playerResponse.isEmpty()) {
			System.out.println("没有任何操作");
			return null;
		}
		if (playerResponse.size() > 1) {
			System.out.println("有很多操作，请检查");
		}
		// 找到一个合适的响应并执行
		MahjongRound round = RoundUtil.getInstance().createRound(this, playerResponse.remove(0), table);
		table.setCurrentRound(round);
		return null;
	}

	@Override
	public void before() {
		// 通知其他玩家暗杠了
		// 删除玩家手中的N张牌
		MahjongGamer gamer = table.getGamerByPlayerID(currentId);
		operationCard = gamer.removeCard(response.getCard(), deleteNum, true);
		if (response.getType() == Operation.GANG_M) {
			Mahjong responseCard = response.getCard();
			operationCard.add(responseCard);
		}
		if (response.getType() == Operation.GANG_B) {
			gamer.addGroup(response.getCard(), response.getType());
		} else {
			gamer.addGroup(operationCard, response.getType());
		}

		// 通知有人杠
		NotifyPlayerOperation.Builder notifyGang = NotifyPlayerOperation.newBuilder();
		notifyGang.setUserID(response.getOperationId());
		notifyGang.setType(response.getType());
		notifyGang.addAllMj(MahjongCardUtil.getInstance().toMahjongs(operationCard));
		//积分
		String income = MahjongIncome.toJsonString(accounting());
		notifyGang.setIncome(income);
		
		table.broadcast(notifyGang.build());
		table.setTouchPlayerId(currentId);
		table.addRound(this);
		table.startRound(scoure.getOperationId());
	}

	@Override
	public MahjongOperationResponse getScoreResponse() {
		return response;
	}

	@Override
	public boolean isAoutoNext() {
		return false;
	}

	@Override
	public String toString() {
		MahjongGamer gamer = table.getGamerByPlayerID(currentId);
		return String.format("玩家%s 杠牌 %s 杠牌后的手牌：%s", currentId, response.getCard(), gamer.getHandCards());
	}

	@Override
	public Collection<Long> getCanResponseList() {
		return Arrays.asList(currentId);
	}

	/**
	 * 算账 void
	 */
	public Collection<MahjongIncome> accounting() {
		MahjongGamer winer = table.getGamerByPlayerID(currentId);
		int baseScore = table.getGameRules().getBaseScore();// 底分
		// 庄闲翻倍
		if(table.getGameRules().getRoomConfig().getBanker()) {
			if(table.getBankID().equals(winer.getPlayerID())) {
				baseScore *= 2;
			}
		}
		
		Collection<Long> players;
		List<MahjongIncomeInfo> incomeInfo = new ArrayList<MahjongIncomeInfo>();
		int total = 0;
		ArrayList<MahjongIncome> list = new ArrayList<MahjongIncome>();
		IconmeType iconmeType = null;
		if (response.getType() == Operation.GANG_A) {
			iconmeType = IconmeType.AnGang;
		} else if (response.getType() == Operation.GANG_B) {
			iconmeType = IconmeType.BaGang;
		} else if (response.getType() == Operation.GANG_M) {
			iconmeType = IconmeType.MingGang;
		}
		if (response.getType() == Operation.GANG_A || response.getType() == Operation.GANG_B) {
			if (response.getType() == Operation.GANG_A) {
				baseScore *= 2;
			}
			players = table.getSurvivalPlayers(currentId);
			for (long id : players) {
				boolean isBank = false;
				if(table.getGameRules().getRoomConfig().getBanker()) {
					if(table.getBankID().equals(id)) {
						baseScore *= 2;
						isBank = true;
					}
				}
				MahjongGamer gamer = table.getGamerByPlayerID(id);
				baseScore = gamer.getRealMoney(baseScore);
				MahjongIncome mi = new MahjongIncome(id, -baseScore, iconmeType, null,
						MahjongIncomeInfo.build(currentId, baseScore));
				list.add(mi);
				gamer.addIncome(mi);
				incomeInfo.add(MahjongIncomeInfo.build(id, baseScore));
				total += baseScore;
				if(isBank) {
					baseScore /= 2;
				}
			}
		} else {
			players = new ArrayList<>();
			MahjongGamer scoureGamer = table.getGamerByPlayerID(scoure.getOperationId());
			if(table.getGameRules().getRoomConfig().getBanker()) {
				if(table.getBankID().equals(scoureGamer.getPlayerID())) {
					baseScore *= 2;
				}
			}
			baseScore = scoureGamer.getRealMoney(baseScore);
			MahjongIncome mi = new MahjongIncome(scoureGamer.getPlayerID(), -baseScore, iconmeType, null,
					MahjongIncomeInfo.build(currentId, baseScore));
			list.add(mi);
			incomeInfo.add(MahjongIncomeInfo.build(scoureGamer.getPlayerID(), baseScore));
			players.add(scoureGamer.getPlayerID());
			scoureGamer.addIncome(mi);
			total += baseScore;
		}
		total = winer.getRealMoney(total);
		MahjongIncome win = new MahjongIncome(currentId, total, iconmeType, null, incomeInfo);
		winer.addIncome(win);
		table.setLastGangIncome(win);
		list.add(win);
		return list;
	}

	@Override
	public StandingsRound toStandingsRound() {
		StandingsRound sr = new StandingsRound(StandingsOperationType.Gang,currentId, null, operationCard);
		sr.setOperation(response.getType());
		return sr;
	}

	@Override
	public String getInfo() {
		return String.format("牌桌ID:%s --- 玩家:%s 杠牌回合",table.getID(), currentId);
	}
	
	
}
